from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.utils import timezone
from django.db.models import Q, Count
from django.db import transaction
from typing import Dict, Any

from .models import (
    NotificationTemplate, Notification, NotificationPreference,
    NotificationChannel, NotificationLog
)
from .serializers import (
    NotificationTemplateSerializer, NotificationSerializer,
    NotificationPreferenceSerializer, NotificationChannelSerializer,
    NotificationLogSerializer, NotificationCreateSerializer,
    NotificationBatchSerializer, NotificationStatsSerializer
)
from .services import NotificationService, TemplateService


class NotificationTemplateViewSet(viewsets.ModelViewSet):
    """
    通知模板视图集
    """
    queryset = NotificationTemplate.objects.all()
    serializer_class = NotificationTemplateSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 过滤参数
        template_type = self.request.query_params.get('type')
        is_active = self.request.query_params.get('is_active')
        
        if template_type:
            queryset = queryset.filter(template_type=template_type)
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
            
        return queryset.order_by('-created_at')
    
    @action(detail=True, methods=['post'])
    def preview(self, request, pk=None):
        """
        预览模板
        """
        template = self.get_object()
        context = request.data.get('context', {})
        
        try:
            service = TemplateService()
            preview_data = service.preview_template(template, context)
            return Response(preview_data)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=True, methods=['post'])
    def test_send(self, request, pk=None):
        """
        测试发送
        """
        template = self.get_object()
        recipient = request.data.get('recipient')
        context = request.data.get('context', {})
        
        if not recipient:
            return Response(
                {'error': '收件人不能为空'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            service = NotificationService()
            result = service.send_test_notification(
                template=template,
                recipient=recipient,
                context=context
            )
            return Response(result)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )


class NotificationViewSet(viewsets.ModelViewSet):
    """
    通知视图集
    """
    queryset = Notification.objects.all()
    serializer_class = NotificationSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user
        
        # 只显示当前用户的通知
        queryset = queryset.filter(recipient=user)
        
        # 过滤参数
        is_read = self.request.query_params.get('is_read')
        notification_type = self.request.query_params.get('type')
        priority = self.request.query_params.get('priority')
        
        if is_read is not None:
            queryset = queryset.filter(is_read=is_read.lower() == 'true')
        if notification_type:
            queryset = queryset.filter(notification_type=notification_type)
        if priority:
            queryset = queryset.filter(priority=priority)
            
        return queryset.order_by('-created_at')
    
    def get_serializer_class(self):
        if self.action == 'create':
            return NotificationCreateSerializer
        elif self.action == 'batch_create':
            return NotificationBatchSerializer
        return super().get_serializer_class()
    
    @action(detail=True, methods=['post'])
    def mark_read(self, request, pk=None):
        """
        标记为已读
        """
        notification = self.get_object()
        notification.is_read = True
        notification.read_at = timezone.now()
        notification.save()
        
        return Response({'status': 'marked as read'})
    
    @action(detail=False, methods=['post'])
    def mark_all_read(self, request):
        """
        标记所有为已读
        """
        user = request.user
        count = Notification.objects.filter(
            recipient=user,
            is_read=False
        ).update(
            is_read=True,
            read_at=timezone.now()
        )
        
        return Response({'count': count})
    
    @action(detail=False, methods=['post'])
    def batch_create(self, request):
        """
        批量创建通知
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        try:
            with transaction.atomic():
                service = NotificationService()
                result = service.batch_send_notifications(
                    template_id=serializer.validated_data['template_id'],
                    recipients=serializer.validated_data['recipients'],
                    context=serializer.validated_data.get('context', {}),
                    channels=serializer.validated_data.get('channels', ['system'])
                )
                return Response(result)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def stats(self, request):
        """
        通知统计
        """
        user = request.user
        queryset = Notification.objects.filter(recipient=user)
        
        stats = {
            'total': queryset.count(),
            'unread': queryset.filter(is_read=False).count(),
            'read': queryset.filter(is_read=True).count(),
            'by_type': dict(
                queryset.values('notification_type')
                .annotate(count=Count('id'))
                .values_list('notification_type', 'count')
            ),
            'by_priority': dict(
                queryset.values('priority')
                .annotate(count=Count('id'))
                .values_list('priority', 'count')
            )
        }
        
        serializer = NotificationStatsSerializer(stats)
        return Response(serializer.data)


class NotificationPreferenceViewSet(viewsets.ModelViewSet):
    """
    通知偏好视图集
    """
    queryset = NotificationPreference.objects.all()
    serializer_class = NotificationPreferenceSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return super().get_queryset().filter(user=self.request.user)
    
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)
    
    @action(detail=False, methods=['get'])
    def my_preferences(self, request):
        """
        获取我的偏好设置
        """
        user = request.user
        preferences = NotificationPreference.objects.filter(user=user)
        serializer = self.get_serializer(preferences, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['post'])
    def batch_update(self, request):
        """
        批量更新偏好设置
        """
        user = request.user
        preferences_data = request.data.get('preferences', [])
        
        try:
            with transaction.atomic():
                for pref_data in preferences_data:
                    notification_type = pref_data.get('notification_type')
                    channel = pref_data.get('channel')
                    is_enabled = pref_data.get('is_enabled', True)
                    
                    preference, created = NotificationPreference.objects.get_or_create(
                        user=user,
                        notification_type=notification_type,
                        channel=channel,
                        defaults={'is_enabled': is_enabled}
                    )
                    
                    if not created:
                        preference.is_enabled = is_enabled
                        preference.save()
                
                return Response({'status': 'preferences updated'})
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )


class NotificationChannelViewSet(viewsets.ModelViewSet):
    """
    通知渠道视图集
    """
    queryset = NotificationChannel.objects.all()
    serializer_class = NotificationChannelSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 过滤参数
        channel_type = self.request.query_params.get('type')
        is_active = self.request.query_params.get('is_active')
        
        if channel_type:
            queryset = queryset.filter(channel_type=channel_type)
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
            
        return queryset.order_by('channel_type', 'name')
    
    @action(detail=True, methods=['post'])
    def test_connection(self, request, pk=None):
        """
        测试连接
        """
        channel = self.get_object()
        
        try:
            service = NotificationService()
            result = service.test_channel_connection(channel)
            return Response(result)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )


class NotificationLogViewSet(viewsets.ReadOnlyModelViewSet):
    """
    通知日志视图集（只读）
    """
    queryset = NotificationLog.objects.all()
    serializer_class = NotificationLogSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 过滤参数
        status_filter = self.request.query_params.get('status')
        channel = self.request.query_params.get('channel')
        start_date = self.request.query_params.get('start_date')
        end_date = self.request.query_params.get('end_date')
        
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        if channel:
            queryset = queryset.filter(channel=channel)
        if start_date:
            queryset = queryset.filter(sent_at__gte=start_date)
        if end_date:
            queryset = queryset.filter(sent_at__lte=end_date)
            
        return queryset.order_by('-sent_at')
    
    @action(detail=False, methods=['get'])
    def stats(self, request):
        """
        发送统计
        """
        queryset = self.get_queryset()
        
        stats = {
            'total': queryset.count(),
            'success': queryset.filter(status='success').count(),
            'failed': queryset.filter(status='failed').count(),
            'pending': queryset.filter(status='pending').count(),
            'by_channel': dict(
                queryset.values('channel')
                .annotate(count=Count('id'))
                .values_list('channel', 'count')
            )
        }
        
        return Response(stats)